<?php






class MongoDriver extends LibBase{
	
	private $writeHandle = null;
	private $readHandle = null;
	private $mongoHandle = null;

	/**
	 * 构造函数，初始化插件
	 */
	public function __construct($conf) {
		parent::__construct();
		if(isset($conf['type']) && 'replication'==strtolower($conf['type'])){
			$uri = 'mongodb://';
			$uri .= $conf['primary']['host'].':'.$conf['primary']['port'].',';
			$uri .= $conf['secondary'][0]['host'].':'.$conf['secondary'][0]['port'];

			$options = array(
					'replicaSet' => $conf['replicaSet'],
					'readPreference' => MongoClient::RP_PRIMARY_PREFERRED
			);

			try{
				$this->mongoHandle = new MongoClient($uri, $options);
			}catch(MongoException $e){
				n_logSave('mongoconnction.txt',var_export($e->getMessage(),true));
			}
		}else{
			$this->mongoHandle = new MongoClient("mongodb://{$conf['host']}:{$conf['port']}");
		}
		
	}

	/**
	 * 
	 * 获取所有数据库列表
	 */

	public function getDbLists(){
		return $this->mongoHandle->listDBs();
	}

	/**
	 * 
	 * 选择数据库
	 * 
	 * @param string $dbname
	 */

	public function useDb($dbname){
		$this->writeHandle = $this->readHandle = $this->mongoHandle->selectDB($dbname);
	}

	public function getLastError(){
		return $this->writeHandle->lastError();
	}

	public function close(){
		return $this->writeHandle->close();
	}

	/**
	 * 
	 * 获得自增id
	 * 
	 * @param string $dbname
	 */
	private function getNextId($mongo,$collection,$name,$param=array()){
		$param += array(   //默认ID从1开始,间隔是1  
       		'init' => 1,  
       		'step' => 1,  
     	);  

     	$update = array('$inc'=>array('id'=>$param['step']));   //设置间隔  
     	$query = array('name'=>$name);
     	$command = array(  
        	'findandmodify' => 'ids',
        	'update' => $update,  
        	'query' => $query,
        	'upsert' => true,
        	'new' => true  
     	);  
  
     	$id = $mongo->command($command);
     	if (isset($id['value']['id'])) {  
       		return $id['value']['id'];  
     	}else{

        	$mongo->ids->insert(array(  
           		'name' => $name,  
           		'id' => $param['init'],     //设置ID起始数值  
        	));  
        	return $param['init'];  
    	}
	}

	/**
	 * 
	 * 插入自增数据
	 * 
	 * @param string $dbname
	 */
	public function insertAI($collection,$val,$options=array()){
		$id = $this->getNextId($this->writeHandle,$collection,$collection.'Id');
		$val['_id'] = $id;
		return $this->insert($collection,$val,$options);
	}
	
	/**
	 * 
	 * 插入数据
	 * 
	 * @param unknown_type $key
	 * @param unknown_type $val
	 * @param unknown_type $safe
	 */
	public function insert($collection,$val,$options=array()){
		
		try{
			$collectionHandle = new MongoCollection($this->writeHandle,$collection);

			$ret = $collectionHandle->insert($val,$options);
			return $val['_id']->{'$id'};
		}catch (MongoException $e){
			n_logSave('mongoerror.txt',var_export($e->getMessage(),true));
		}
	}
	
	public function batchInsert($collection, $mongoDatas, $options=array()){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		$ret = $collectionHandle->batchInsert($mongoDatas, $options);

		if($ret){
			return n_state(true, "添加成功");
		}else{
			return n_state(false, "添加失败");
		}

	}
	
	public function find($collection, $query, $columns=array(), $skip=0 ,$limit=0, $sort=array()){

		$collectionHandle = new MongoCollection($this->readHandle, $collection);

		if(!empty($columns) && is_array($columns)){
			/*$tColumns = array();
			foreach ($columns as $value) {
				$tColumns[$value] = true;
			}*/
			$datas = $collectionHandle->find($query,$columns);
		}else
			$datas = $collectionHandle->find($query);

		if(!empty($sort)){

			$datas = $datas->sort($sort);
		}

		if(!empty($skip)){

			$datas = $datas->skip($skip);
		}

		if(!empty($limit)){

			$datas = $datas->limit($limit);
		}

		return iterator_to_array($datas);

	}

	public function save($collection, $mongoData, $options=array()){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		return $collectionHandle->save($mongoData, $options);
	}

	public function update($collection, $where, $data , $options=array()){
		try{
			$collectionHandle = new MongoCollection($this->writeHandle, $collection);

			$newdata = array('$set' => $data);

			return $collectionHandle->update($where,$newdata, $options);
		}catch (MongoException $e){
			n_logSave('mongoerror.txt',var_export($e->getMessage(),true));
		}
	}

	public function group($collection,$keys,$initial,$reduce,$options=array()){
		$collectionHandle = new MongoCollection($this->readHandle, $collection);

		return $collectionHandle->group($keys,$initial,$reduce,$options);
	}

	public function _get_index_info($collection){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		return $collectionHandle->getindexinfo();
	}

	public function findAndModify($collection, $query, $update, $options=array()){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		return $collectionHandle->findAndModify($query, $update, null, $options);
	}


	public function remove($collection, $query, $options=array()){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		return $collectionHandle->remove($query, $options);

	}

	public function findOne($collection, $query=array(), $columns=array(), $options=array()){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		return $collectionHandle->findOne($query, $columns, $options);
	}

	public function count($collection, $query=array(), $options=array()){

		$collectionHandle = new MongoCollection($this->readHandle, $collection);

		return $collectionHandle->count($query);
	}

	public function collection($collection){
		return new MongoCollection($this->readHandle,$collection);
	}
	

	public function get($collection,$id){
		$collectionHandle = new MongoCollection($this->readHandle,$collection);
		
		if(!is_array($id)){
			$id = array($id);
		}
		
		$rs = $collectionHandle->find(array('id'=>array('$in'=>$id)));
		return iterator_to_array($rs);
	}

	public function aggregate($collection, $ops){

		$collectionHandle = new MongoCollection($this->readHandle,$collection);

		return $collectionHandle->aggregate($ops);
	}
	
	public function drop($collection){

		$collectionHandle = new MongoCollection($this->writeHandle, $collection);

		$ret = $collectionHandle->drop();

		if($ret['ok']){
			return n_state(true, "ok");
		}else{
			return n_state(false, "fail");
		}
	}
	public function del($collection,$id){
		$collection = $this->isExists($collection);
//		$rs = $collection->find(array('_id' => new MongoId($id)))->limit(10);
//		echo '===';
//		foreach($rs as $key1=>$val1){
//			echo $key1;
//			print_r($val1);
//		}
		$collection->remove(array('_id' => new MongoId($id)),true);
//		header("location: ".n_url('datalist')."&");
	}
	
	 
	
	private function isExists($param){
		
		$lc = $this->dbHandle->listCollections();
		foreach($lc as $key=>$val){
			if($param==$val->getName()){
				$collection = $val;
			}
		}
		if(!isset($collection)){
			throw new PException("找不到聚集");
		}
		return $collection;
		
	}

}

